#pragma once
#include "protocol.h"
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <vector>
#include <list>
using namespace boost::asio;
using namespace boost::posix_time;

#include <crtdbg.h> 
//#define NBEIMPORT
#include "NBE.h"

#include "RenderSystem.h"
#include "gameState.h"

#include "ShaderManager.h"
#include "TextureManager.h"
#include "Camera.h"
#include "Input.h"

#include "player.h"
#include "bullet.h"
#include "MyTimer.h"

#ifdef _DEBUG
#define trace( text )\
{\
	std::wstringstream stringBuilder;\
	stringBuilder << text << std::endl;\
	OutputDebugString(stringBuilder.str().c_str());\
}
#endif


using namespace NBE;
namespace NOEXIT
{
	class Game:public Listener
	{
	public:
		Game(HINSTANCE h);
		~Game();
		RenderInfo* loadRenderInfo(wchar_t* cfgname);
		void run();
		void initMap();
		void initNetwork();
		void deleteNetwork();
		void login();
		void updateFrame();
		void drawRO(RenderObject* ro, Matrix4f& worldMat);

		void handleEvent(Event* e);
		void handleKeyDown(int key);
		void handleKeyRelease(int key);
		//
		void startSend();
		void startSend_Guarantee();
		void startReceive();
		void receiver();
		void keepalive();

		void MsgHandler(const boost::system::error_code& ec,std::size_t bytes_transferred);
		void SendMsgHandler(const boost::system::error_code& ec,std::size_t bytes_transferred);
		void clearGuaranteeMsgs(long long msgOrder);

		//logic
		void updatePlayers(int num, PlayerInfo* parray);
		Player* getPlayerById(int id);
		void removePlayerById(int id);
		void createPlayerRO(Player* p);
		void creaetBulletRO(Bullet* b);
		void checkHeartBeat();
		void shoot(Player* p);
		void addBullet(BulletInfo* binfo);
		void removeBullet(BulletInfo* binfo);
	private: 
		Config cfg;
		std::shared_ptr<RenderSystem> m_pRenderer;
		std::vector<RenderObject*> m_renderObjVec;

		GAMESTATE currentState;
		gameInitInfo initInfo;
		ShaderManager* shaderMgr;
		uint generalShader;

		TextureManager* textureMgr;

		std::shared_ptr<Camera> m_pCamera;
		std::vector<Input*> m_inputVec;

		std::list<Player*> playerList;
		std::list<Bullet*> bulletList;
		Player* currentPlayer;
		RenderObject* map;

		///
		std::vector<SMsg> NeedToSend;
		std::list<SMsg> NeedToSend_Guarantee;
		long long rtt;
		

		long long localGuarantee;
		long long serverGuarantee;//server's g msgs need to ack them back

		//timing
		clocks m_startFrameTime;
		clocks m_nextUpdateTime;
		Time m_timer;

		ptime startpt;//start time for network
		long long sendNow;
		long long lastTimeSend;

		long long sendMove;
	    long long lastTimeSendMove;
		long long rttCheckNow;
		long long lastTimeRttCheck;

		long long sendGuaranteeNow;
		long long lastTimeGuarantee;
		bool GuaranteeSendFlag;
		///
		char byteData[BUFFSIZE];
		char rcvByteData[BUFFSIZE];
		ip::udp::socket* mySocket;
		ip::udp::endpoint server_address;
		int sessionId;
		io_service service;

	
	};
}